package ar.edu.utn.frsf.tpae.a2014.g02.persistence.dao.impl;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ar.edu.utn.frsf.tpae.a2014.g02.persistence.dao.UsuarioDao;
import ar.edu.utn.frsf.tpae.a2014.g02.persistence.model.Administrador;
import ar.edu.utn.frsf.tpae.a2014.g02.persistence.model.Cliente;
import ar.edu.utn.frsf.tpae.a2014.g02.persistence.model.Transportista;
import ar.edu.utn.frsf.tpae.a2014.g02.persistence.model.Usuario;

/**
 * DAO de Usuario basado en Hibernate.
 * 
 * @author TPAE
 */
@Component
public class UsuarioHibernateDao implements UsuarioDao {

	private SessionFactory sessionFactory;

	// Setter utilizado por Spring.
	@Autowired(required = true)
	public void setSessionFactory(SessionFactory factory) {
		this.sessionFactory = factory;
	}

	private Session getCurrentSession() {
		return sessionFactory.getCurrentSession();
	}

	public Usuario persistir(Usuario usuario) {
		getCurrentSession().saveOrUpdate(usuario);
		return usuario;
	}

	@SuppressWarnings("unchecked")
	public List<Usuario> listar() {
		Query query = getCurrentSession().createQuery("from Usuario");
		List<Usuario> lista = (List<Usuario>) query.list();
		return lista;
	}

	public void deleteAll() {
		Query query = getCurrentSession().createQuery(
				"delete from " + Usuario.class.getName());
		query.executeUpdate();
	}

	public Usuario recuperarSegunNombreUsuario(String usuario) {
		Session session = getCurrentSession();
		Query query = session.createQuery("select user.id from Usuario user"
				+ " where user.usuario = :usuario");
		query.setParameter("usuario", usuario);
		Integer idUser = (Integer) query.uniqueResult();

		String selectCount = "select count(*) ";
		String from = "from ";
		String whereId = " where usuario.id = :id";
		String clienteWhere = " Cliente cli " + whereId;
		String administradorWhere = " Administrador admin " + whereId;
		String transportistaWhere = " Transportista tra " + whereId;

		Query cliente = session.createQuery(selectCount + from + clienteWhere);
		cliente.setParameter("id", idUser);
		Query administrador = session.createQuery(selectCount + from
				+ administradorWhere);
		administrador.setParameter("id", idUser);
		Query transportista = session.createQuery(selectCount + from
				+ transportistaWhere);
		transportista.setParameter("id", idUser);

		Usuario user = null;

		if ((Long) cliente.uniqueResult() == 1) {
			user = (Cliente) session.createQuery(from + clienteWhere)
					.setParameter("id", idUser).uniqueResult();
		} else if ((Long) administrador.uniqueResult() == 1) {
			user = (Administrador) session
					.createQuery(from + administradorWhere)
					.setParameter("id", idUser).uniqueResult();
		} else if ((Long) transportista.uniqueResult() == 1) {
			user = (Transportista) session
					.createQuery(from + transportistaWhere)
					.setParameter("id", idUser).uniqueResult();
		} else {
			user = (Usuario) session.createQuery(from + " Usuario " + whereId)
					.setParameter("id", idUser).uniqueResult();
		}

		return user;
	}

	public Boolean validaUsuarioYContrasenia(String usuario, String contrasenia) {
		Usuario user = this.recuperarSegunNombreUsuario(usuario);

		if (user != null) {
			return user.getContrasenia().equals(contrasenia);
		}
		return false;
	}
}
